<?php
/**
 * Calendar management class.
 * @package Vanilla
 */
class CalendarManager extends Delegation {
	var $Name;				// The name of this class
	var $Context;			// The context object that contains all global objects (database, error manager, warning collector, session, etc)

	function CalendarManager(&$Context) {
		$this->Name = 'CalendarManager';
		$this->Delegation($Context);
		$this->CallDelegate('Constructor');
	}

	function GetCalendarBuilder($IncludeCount = '0', $ForceRoleBlock = '1') {
		$this->CallDelegate('PreGetCalendarBuilder');
		$IncludeCount = ForceBool($IncludeCount, 0);
		$sql = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
		$sql->SetMainTable('Calendar', 'Calendar');
		$sql->AddSelect(array('CalendarID', 'Title', 'Description', 'RequireApproval', 'Color','Priority'), 'Calendar');
		$sql->AddGroupBy ('CalendarID','Calendar');
		if ($IncludeCount) {
			$sql->AddJoin('Event', 'Event', 'CalendarID', 'Calendar', 'CalendarID', 'LEFT JOIN', " AND Event.".$this->Context->DatabaseColumns['Event']['Approved']." = 1");
			$sql->AddSelect('EventID', 'Event', 'EventCount', 'COUNT');
		}
		if ($this->Context->Session->UserID > 0) {
			$sql->AddJoin('CalendarRoleBlock', 'CalendarRoleBlock', 'CalendarID', 'Calendar', 'CalendarID', 'LEFT JOIN', ' AND CalendarRoleBlock.'.$this->Context->DatabaseColumns['CalendarRoleBlock']['RoleID'].' = '.$this->Context->Session->User->RoleID);
			$sql->AddJoin('CalendarBlock', 'CalendarBlock', 'CalendarID', 'Calendar', 'CalendarID', 'left join', ' AND CalendarBlock.'.$this->Context->DatabaseColumns['CalendarBlock']['UserID'].' = '.$this->Context->Session->UserID);
			$sql->AddSelect('Blocked', 'CalendarBlock', 'Blocked', 'COALESCE', '0');
		} else {
			$sql->AddJoin('CalendarRoleBlock', 'CalendarRoleBlock', 'CalendarID', 'Calendar', 'CalendarID', 'LEFT JOIN', ' AND CalendarRoleBlock.'.$this->Context->DatabaseColumns['CalendarRoleBlock']['RoleID'].' = 1');
		}
		$BlockCalendarsByRole = 1;
		if ($this->Context->Session->User->Permission('PERMISSION_VCAL_ADD_CALENDAR')
			|| $this->Context->Session->User->Permission('PERMISSION_VCAL_EDIT_CALENDAR')
			|| $this->Context->Session->User->Permission('PERMISSION_VCAL_REMOVE_CALENDAR')) {
				$BlockCalendarsByRole = 0;
		}
		if ($ForceRoleBlock) $BlockCalendarsByRole = 1;
		else $BlockCalendarsByRole = 0;
		// Limit to calendars that this role is allowed to see.
		if ($BlockCalendarsByRole) {
			$sql->AddWhere('CalendarRoleBlock', 'Blocked', '', 0, '=', 'and', '', 1, 1);
			$sql->AddWhere('CalendarRoleBlock', 'Blocked', '', 0, '=', 'or', '', 0);
			$sql->AddWhere('CalendarRoleBlock', 'Blocked', '', 'null', 'is', 'or', '', 0);
			$sql->EndWhereGroup();
		} else {
			// Identify which of these calendars is blocked by role
			// (so administrators can easily see what they do and don't have access to)
			$sql->AddSelect('Blocked', 'CalendarRoleBlock', 'RoleBlocked', 'COALESCE', '0');
		}

		$this->DelegateParameters['IncludeCount'] = $IncludeCount;
		$this->DelegateParameters['ForceRoleBlock'] = $ForceRoleBlock;
		$this->DelegateParameters['SqlBuilder'] = &$sql;
		$this->CallDelegate('PostGetCalendarBuilder');
		return $sql;
	}
	function GetCalendars($IncludeCount = '0', $OrderByPreference = '0', $ForceRoleBlock = '1') {
		$OrderByPreference = ForceBool($OrderByPreference, 0);
		$sql = $this->GetCalendarBuilder($IncludeCount, $ForceRoleBlock);
		if ($OrderByPreference && $this->Context->Session->UserID > 0) {
			// Order by the user's preference (unblocked calendars first)
			$sql->AddOrderBy('Blocked', 'CalendarBlock', 'ASC');
		}
		$sql->AddOrderBy('Priority', 'Calendar', 'ASC');
		$ResultSet = $this->Context->Database->Select($sql, $this->Name, 'GetCalendars', 'An error occurred while retrieving Calendars.');
		return $ResultSet;
	}
	
	function GetCalendarById($CalendarID = "0") {
		$Calendar = $this->Context->ObjectFactory->NewObject($this->Context, 'Calendars');
		$sql = $this->GetCalendarBuilder(0, 0);
		$sql->AddWhere('Calendar', 'CalendarID', '', $CalendarID, '=');
		$this->CallDelegate('GetCalendarById');
		$ResultSet = $this->Context->Database->Select($sql, $this->Name, 'GetCalendarById', 'An error occurred while attempting to retrieve the requested Calendar.');
		if ($this->Context->Database->RowCount($ResultSet) == 0) $this->Context->WarningCollector->Add($this->Context->GetDefinition('ErrCalendarNotFound'));
		while ($rows = $this->Context->Database->GetRow($ResultSet)) {
			$Calendar->GetPropertiesFromDataSet($rows);
			$Calendar->FormatPropertiesForDisplay();
		}
		return $this->Context->WarningCollector->Iif($Calendar, false);
	}

	function GetCalendarRoleBlocks($CalendarID = '0') {
		$sql = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
		$sql->SetMainTable('Role', 'Role');
		$sql->AddJoin('CalendarRoleBlock', 'CalendarRoleBlock', 'RoleID', 'Role', 'RoleID', 'LEFT JOIN', ' AND CalendarRoleBlock.'.$this->Context->DatabaseColumns['CalendarRoleBlock']['CalendarID'].' = '.$CalendarID);
		$sql->AddSelect(array('RoleID', 'Name'), 'Role');
		$sql->AddSelect('Blocked', 'CalendarRoleBlock', 'Blocked', 'coalesce', '0');
		$sql->AddWhere('Role', 'Active', '', '1', '=');
		$sql->AddOrderBy('Priority', 'Role', 'asc');
		$this->CallDelegate('PostGetCalendarRoleBlocks');

		return $this->Context->Database->Select($sql, $this->Name, 'GetCalendarRoleBlocks', 'An error occurred while retrieving Calendar role blocks.');
	}

	function RemoveCalendar($RemoveCalendarID, $ReplacementCalendarID) {
		$ReplacementCalendarID = ForceInt($ReplacementCalendarID, 0);
		if ($ReplacementCalendarID <= 0) {
			$this->Context->WarningCollector->Add($this->Context->GetDefinition('ErrCalendarReplacement'));
			return false;
		}
		// Reassign the user-assigned calendars
		$sql = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
		$sql->SetMainTable('Event', 'Event');
		$sql->AddFieldNameValue('CalendarID', $ReplacementCalendarID);
		$sql->AddWhere('Event', 'CalendarID', '', $RemoveCalendarID, '=');
		$resultset = $sql->GetUpdate();
		$this->Context->Database->Update($sql, $this->Name, 'RemoveCalendar', 'An error occurred while attempting to re-assign user calendars.');

		// remove role blocks
		$sql->Clear();
		$sql->SetMainTable('CalendarRoleBlock', 'CalendarRoleBlock');
		$sql->AddWhere('CalendarRoleBlock', 'CalendarID', '', $RemoveCalendarID, '=');
		$resultset = $sql->GetDelete();
		$this->Context->Database->Delete($sql, $this->Name, 'RemoveCalendar', 'An error occurred while attempting to remove role-assigned blocks on the selected Calendar.');

		// Now remove the Calendar itself
		$sql->Clear();
		$sql->SetMainTable('Calendar', 'Calendar');
		$sql->AddWhere('Calendar', 'CalendarID', '', $RemoveCalendarID, '=');
		$this->Context->Database->Delete($sql, $this->Name, 'RemoveCalendar', 'An error occurred while attempting to remove the Calendar.');
		return true;
	}

	function SaveCalendar(&$Calendar) {
		// Validate the properties
		if($this->ValidateCalendar($Calendar)) {
			$sql = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
			$sql->SetMainTable('Calendar', 'Calendar');
			$sql->AddFieldNameValue('Title', $Calendar->Title);
			$sql->AddFieldNameValue('Description', $Calendar->Description);
			$sql->AddFieldNameValue('RequireApproval', $Calendar->RequireApproval);
			$sql->AddFieldNameValue('Color', $Calendar->ColorStr);
			//$sql->AddFieldNameValue('CustomFields', $Calendar->CustomFieldsStr);

			// If creating a new calendar
			if ($Calendar->CalendarID == 0) {
				$Calendar->CalendarID = $this->Context->Database->Insert($sql, $this->Name, 'SaveCalendar', 'An error occurred while creating a new Calendar.');
			} else 	{
				$sql->AddWhere('Calendar', 'CalendarID', '', $Calendar->CalendarID, '=');
				$this->Context->Database->Update($sql, $this->Name, 'SaveCalendar', 'An error occurred while attempting to update the Calendar.');
			}

			// Now update the blocked roles
			$sql->Clear();
			$sql->SetMainTable('CalendarRoleBlock', 'CalendarRoleBlock');
			$sql->AddWhere('CalendarRoleBlock', 'CalendarID', '', $Calendar->CalendarID, '=');
			$this->Context->Database->Delete($sql, $this->Name, 'SaveCalendar', 'An error occurred while removing old role block definitions for this Calendar.');

			$Calendar->AllowedRoles[] = 0;

			$sql->Clear();
			$sql->SetMainTable('Role', 'Role');
			$sql->AddSelect('RoleID', 'Role');
			$sql->AddWhere('Role', 'Active', '', 1, '=');
			$sql->AddWhere('Role', 'RoleID', '', '('.implode(',',$Calendar->AllowedRoles).')', 'not in', 'and', '', 0);
			$BlockedRoles = $this->Context->Database->Select($sql, $this->Name, 'SaveCalendar', 'An error occurred while retrieving blocked roles.');

			while ($Row = $this->Context->Database->GetRow($BlockedRoles)) {
				$RoleID = ForceInt($Row['RoleID'], 0);
				if ($RoleID > 0) {
					$sql->Clear();
					$sql->SetMainTable('CalendarRoleBlock', 'CalendarRoleBlock');
					$sql->AddFieldNameValue('CalendarID', $Calendar->CalendarID);
					$sql->AddFieldNameValue('RoleID', $RoleID);
					$sql->AddFieldNameValue('Blocked', 1);
					$this->Context->Database->Insert($sql, $this->Name, 'SaveCalendar', 'An error occurred while adding new role block definitions for this Calendar.');
				}
			}
		}
		return $this->Context->WarningCollector->Iif($Calendar, false);
	}

	function SaveCalendarOrder() {
		$sql = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
		$ItemCount = ForceIncomingInt('SortItemCount', 0) + 1;
		for ($i = 1; $i < $ItemCount; $i++) {
			$CalendarID = ForceIncomingInt('Sort_'.$i, 0);
			if ($CalendarID > 0) {
				$sql->Clear();
				$sql->SetMainTable('Calendar', 'Calendar');
				$sql->AddFieldNameValue('Priority', $i);
				$sql->AddWhere('Calendar', 'CalendarID', '', $CalendarID, '=');
				$this->Context->Database->Update($sql, $this->Name, 'SaveCalendarOrder', 'An error occurred while attempting to update the Calendar sort order.', 0);
			}
		}
	}

	// Validates and formats properties ensuring they're safe for database input
	// Returns: boolean value indicating success
	function ValidateCalendar(&$Calendar) {
		// First update the values so they are safe for db input
		$ValidatedCalendar = $Calendar;
		$ValidatedCalendar->FormatPropertiesForDatabaseInput($this->Context);

		// Instantiate a new validator for each field
		Validate($this->Context->GetDefinition('CalendarNameLower'), 1, $ValidatedCalendar->Title, 100, '', $this->Context);

		// If validation was successful, then reset the properties to db safe values for saving
		if ($this->Context->WarningCollector->Count() == 0) $Calendar = $ValidatedCalendar;

		return $this->Context->WarningCollector->Iif();
	}
	function AddCalendarBlock($CalendarID) {
		$sql = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
		$sql->SetMainTable('CalendarBlock', 'CalendarBlock');
		$sql->AddFieldNameValue('UserID', $this->Context->Session->UserID);
		$sql->AddFieldNameValue('CalendarID', $CalendarID);
		$sql->AddFieldNameValue('Blocked', 1);
		$this->Context->Database->Insert($sql, $this->Name, 'AddCalendarBlock', 'Failed to add calendar block.', 0, 0);
	}
	
	function RemoveCalendarBlock($CalendarID) {
		$sql = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
		$sql->SetMainTable('CalendarBlock', 'CalendarBlock');
		$sql->AddWhere('CalendarBlock', 'CalendarID', '', $CalendarID, '=');
		$sql->AddWhere('CalendarBlock', 'UserID', '', $this->Context->Session->UserID, '=');
		$this->Context->Database->Delete($sql, $this->Name, 'RemoveCalendarBlock', 'An error occurred while removing the calendar block.', 0);
	}
}
?>